﻿XBox = XBox || { global: window };
XBox.ui = XBox.ui ||
{
    svgIcon: {
        close: '<svg height="16" version="1.1" viewBox="0 0 12 16" width="12"><path class="ui-red" fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path></svg>',
        plus: '<svg height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M1 4H10V13H1V5z" style="fill:transparent;stroke:#666;stroke-width:.5"></path><path fill-rule="evenodd" d="M10 9H6v4H5V9H1V8H5V4H6V8H10z"></path></svg>',
        minus: '<svg height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M1 4H10V13H1V5z" style="fill:transparent;stroke:#666;stroke-width:.5"></path><path fill-rule="evenodd" d="M10 9H1V8H10V9Z"></path></svg>',
        up: '<svg height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 11L7 5L2 11Z"></path></svg>',
        down: '<svg height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 6L7 12L2 6Z"></path></svg>'
    },
    util: {
        /**
         * 获取元素的绝对高度
         * @param {HtmlElement} e 目标元素
         * @returns {number} 元素绝对高度 
         */
        getTop: function (e) {
            if ($(e).length) {
                var ele = $(e)[0];
                var offset = ele.offsetTop;
                if (ele.offsetParent != null) {
                    offset += XBox.ui.util.getTop(ele.offsetParent);
                }
                if (ele.tagName !== "BODY") {
                    offset -= (ele.scrollTop || 0);
                }
                return offset;
            }
            return NaN;
        },

        /**
         * 获取元素的绝对左偏移
         * @param {HtmlElement} e 目标元素
         * @returns {number} 元素绝对左偏移
         */
        getLeft: function getLeft(e) {
            if ($(e).length) {
                var ele = $(e)[0];
                var offset = ele.offsetLeft;
                if (ele.offsetParent != null) {
                    offset += XBox.ui.util.getLeft(ele.offsetParent);
                }
                if (ele.tagName !== "BODY") {
                    offset -= (ele.scrollLeft || 0);
                }
                return offset;
            }
            return NaN;
        }
    }
};
XBox.ui.upload = function (options) {
    var container = $(options.container);

    var imgConfig = options.imgConfig;
    var fileConfig = options.fileConfig;

    //var show = options.show;
    var showError = options.error;

    var save = options.save;
    var remove = options.remove;

    var dir = options.directory || "";

    var template = $(options.template || '<span class="xupload"><span><a href="javascript:void(0);">选择文件</a><input type="file" multiple="multiple"></span></span>');
    template.find("a").html(options.text || "选择文件");

    var imageContainer = options.imageContainer ? $(options.imageContainer) : container;
    var imageTemplate = options.template || '<span class="xupload-file"><span class="remove" title="删除"></span><a class="name" href="javascript:void(0)"><span></span></a></span>';

    container.append(template);

    var check = function (imgConfig, fileConfig, file) {
        var cfg = fileConfig;
        if (file.type.match('image/.*')) {
            cfg = imgConfig;
        }
        if (!cfg) {
            return true;
        }
        var exts = (cfg.AllowExtensions || "").toLowerCase().split(",");
        if (exts.length) {
            var n = file.name;
            var i = n.lastIndexOf(".");
            var ext = n.substr(i + 1).toLowerCase();
            if (exts.indexOf(ext) < 0) {
                return "文件【" + file.name + "】类型不允许。";
            }
        }
        var maxSize = (cfg.MaxLength || 400);
        var size = file.size / 1024;
        if (size > maxSize) {
            return "文件【" + file.name + "】【" + size + "K】超出限制（" + maxSize + "K）。";
        }
        return true;
    }

    var upload = function () {
        var files = $(this)[0].files;

        var imginfo = "";
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            var rst = check(imgConfig, fileConfig, file);
            if (rst !== true) {
                imginfo += rst;
                showError && showError(imginfo, file);
                continue;
            }
            var item = $(imageTemplate);
            item.find(".remove").append(XBox.ui.svgIcon.close);
            item.find("a.name>span").html(file.name);
            imageContainer.append(item);
            //var fr = new FileReader();
            //fr.onloadend = (function (f) {
            //	return function () {
            //		show(this.result, f);
            //	};
            //})(file);
            //fr.readAsDataURL(file);
            item.data("file", file);
            if (save) {
                (function (file, item) {
                    var fd = new FormData();
                    fd.append('file', file);
                    fd.append('dir', dir);
                    $.ajax({
                        url: save,
                        type: "post",
                        data: fd,
                        cache: false,
                        processData: false,
                        contentType: false,
                        success: function (result) {
                            if (result.IsSuccess) {
                                console.log("上传到服务器：" + result.Result);
                                if (file.type.match('image/.*')) {
                                    var img = $("<img>").attr("src", "/" + result.Result);
                                    item.find('a.name').after(img);
                                    item.find('a.name').remove();
                                }
                                item.data("serverPath", result.Result);
                            } else {
                                showError && showError(result.Message, file);
                            }
                        }
                    });
                })(file, item);
            }
        }
        var newJqObj = $(this).clone();
        $(this).before(newJqObj);
        $(this).remove();
    };
    container.delegate("input:file", "change", upload);

    imageContainer.delegate(".xupload-file .remove", "click", function () {
        var xfile = $(this).closest(".xupload-file");
        if (remove) {
            var filepath = xfile.data("serverPath");
            if (filepath) {
                $.ajax({
                    url: remove,
                    type: "post",
                    data: { Data: filepath },
                    success: function (result) {
                        if (result.IsSuccess) {
                            console.log("从服务器上删除：" + filepath);
                        }
                    }
                });
            }
        }
        xfile.remove();
    });

    return {
        container: container,
        value: function () {
            return this.container.find(".xupload-file")
		        .map(function () {
		            return $(this).data("serverPath");
		        }).get();
        }
    }
}

XBox.ui.multiSelect = function (options) {
    options.multiple = XBox.ifNull(options.multiple, true);
    options.groupSelectable = XBox.ifNull(options.groupSelectable, false);

    var init = function (options) {
        var target = $(options.target).addClass("xmultiselect").attr("readonly", "readonly");
        var itemName = options.text || "项目";
        target.val("请选择" + itemName);

        var panel = $("<div>").addClass("xmultipanel");//.data("xboxui-id", id);
        var arrow = $("<span class='arrow down'>").html(XBox.ui.svgIcon.down);
        arrow.find("svg").css("vertical-align", "middle");
        target.after(arrow);

        var close = function (target, arrow, panel, fast) {
            arrow.removeClass("up").addClass("down").html(XBox.ui.svgIcon.down);
            arrow.find("svg").css("vertical-align", "middle");
            if (fast)
                panel.hide();
            else
                panel.slideUp(200);
        }
        var open = function (target, arrow, panel) {
            if (!$(target).attr("disabled")) {
                if (panel.closest("body").length === 0) {
                    arrow.after(panel);
                    var pp = $(target).closest(".k-window");
                    if (pp.length) {
                        panel.css("position", "fixed");
                        pp.find(".k-window-content.k-content").scroll(function () { close(target, arrow, panel); });
                        pp.find(".k-window-titlebar.k-header").mousedown(function () { close(target, arrow, panel, 1); });
                        //pp.append(panel);
                    } else {
                        panel.css("position", "absolute");
                        //arrow.after(panel);
                    }
                }
                //panel.css("opacity", "0").show();
                arrow.removeClass("down").addClass("up").html(XBox.ui.svgIcon.up);
                arrow.find("svg").css("vertical-align", "middle");
                var height = target.height() +
                    parseInt(target.css("padding-top")) +
                    parseInt(target.css("padding-bottom")) +
                    parseInt(target.css("border-top-width")) +
                    parseInt(target.css("border-bottom-width"));
                var bottom = XBox.ui.util.getTop(target);
                var left = XBox.ui.util.getLeft(target);
                var top = bottom + height;

                var width = target.width()
                    + parseInt(target.css("padding-left"))
                    + parseInt(target.css("padding-right"))
                    + parseInt(target.css("border-left-width"))
                    + parseInt(target.css("border-right-width"))
                    - 2;
                var phelght = parseInt(panel.css("height"));
                panel.css("height", phelght + 1 + "px");
                var sy = panel.css("position") === "absolute" ? window.scrollY : 0;
                if ((parseInt(panel.css("height")) + top - sy) > window.innerHeight) {
                    top = false;
                    bottom = window.innerHeight - bottom;
                }
                var lleft = parseInt(panel.css("width")) + left - window.innerWidth;
                if (lleft > 0) {
                    left = left - lleft;
                }
                if (top) {
                    panel.css("bottom", "").css("top", top + "px");
                } else {
                    panel.css("top", "").css("bottom", bottom + "px");
                }
                panel.css("left", left + "px");
                panel.css("min-width", width + "px");

                var others = $(".xmultiselect").not(target);
                others.each(function (i, ele) {
                    var multi = $(ele).data("xboxui-data");
                    multi && multi.close();
                });
                //panel.hide().css("opacity", "1").css("height", "auto");
                panel.slideDown(200);
            }
        }

        var toggle = function (target, arrow, panel) {
            var toShow = arrow.hasClass("down");
            var isShow = panel.is(":visible");
            if (isShow) {
                toShow = false;
            }
            if (toShow) {
                open(target, arrow, panel);
            } else {
                close(target, arrow, panel);
            }
        }

        target.on("click", function (e) { toggle(target, arrow, panel); e.stopPropagation(); });
        arrow.click(function (e) { toggle(target, arrow, panel); e.stopPropagation(); });

        var renderList = function (parent, items, schema, groupTpl, itemTpl, countTpl) {
            if (XBox.isArray(items) && items.length) {
                var ul = $("<ul>");
                for (var i = 0; i < items.length; i++) {
                    var item = items[i];
                    var text, value, hasItems = XBox.isArray(item[schema.childrenField]);
                    if (XBox.isObject(item)) {
                        text = item[schema.textField];
                        value = item[schema.valueField];
                    } else {
                        text = item;
                        value = item;
                    }
                    if (XBox.isNullOrUndefined(text) && XBox.isNullOrUndefined(value)) {
                        continue;
                    }
                    if (XBox.isNullOrUndefined(text)) {
                        text = value;
                    } else if (XBox.isNullOrUndefined(value) && !hasItems) {
                        value = text;
                    }
                    var li = $("<li>");
                    var lii = $(itemTpl);
                    if (hasItems) {
                        lii = $(groupTpl);
                    }
                    if (lii.find("input").length) {
                        lii.append(countTpl);
                    }
                    lii.find("label>input:checkbox").val(value);
                    lii.find("label span").html(text);
                    lii.data("text", text).data("value", value).attr("val", value);
                    li.append(lii);
                    renderList(li, item[schema.childrenField], schema, groupTpl, itemTpl, countTpl);
                    ul.append(li);
                }
                parent.append(ul);
                return true;
            }
            return false;
        }

        var render = function (panel, dataSource, multiple, groupSelectable) {
            var countTpl = '<span class="xcount"></span>';
            var checkAllTpl = '<span class="xcheckall"><label class="checkbox"><input type="checkbox"><i></i><span></span></label><span>';
            var groupTpl = '<span class="xcheckgroup"><span class="xce"></span><label class="checkbox"><input type="checkbox"><i></i><span></span></label></span>';
            var itemTpl = '<span class="xcheckitem"><label class="checkbox"><input type="checkbox"><i></i><span></span></label></span>';
            if (!multiple) {
                groupTpl = '<span class="xcheckgroup"><span class="xce"></span><label><span></span></label></span>';
                if (groupSelectable) {
                    groupTpl = '<span class="xcheckitem xcheckgroup"><span class="xce"></span><label><span></span></label></span>';
                }
                itemTpl = '<span class="xcheckitem"><label><span></span></label></span>';
            }
            var schema = XBox.apply({
                textField: "text",
                valueField: "value",
                childrenField: "items"
            }, dataSource.schema);
            if (multiple) {
                var checkAll = $(checkAllTpl);
                checkAll.append(countTpl);
                checkAll.find("label>input:checkbox").val(null);
                checkAll.find("label span").html("全部" + itemName);
                panel.append(checkAll);
            }
            var data = dataSource.data;
            if (XBox.isArray(data)) {
                renderList(panel, data, schema, groupTpl, itemTpl, countTpl);
            }
            panel.find(".xce").each(function () {
                $(this).addClass("xopen").html(XBox.ui.svgIcon.minus);
            });
        }

        render(panel, options.dataSource, options.multiple, options.groupSelectable);

        panel.find(".xce").click(function () {
            var xce = $(this);
            var ul = xce.closest("li").find("ul:first");
            if (xce.hasClass("xopen")) {
                xce.html(XBox.ui.svgIcon.plus).removeClass("xopen");
                ul.slideUp(200);
            } else {
                xce.html(XBox.ui.svgIcon.minus).addClass("xopen");
                ul.slideDown(200);
            }
        });

        var count = function (panel, target) {
            var groups = panel.find(".xcheckgroup");
            groups.each(function () {
                var chks = $(this).next("ul").find(".xcheckitem input:checkbox");
                var allchkcount = chks.length;
                var checkedcount = chks.filter(":checked").length;
                $(this).find(">input:checkbox").prop("checked", allchkcount === checkedcount);
                $(this).find(".xcount").html("(" + checkedcount + "/" + allchkcount + ")");
            });
            var pchks = panel.find(".xcheckitem input:checkbox");
            var pallchkcount = pchks.length;
            var pcheckedcount = pchks.filter(":checked").length;
            panel.find(".xcheckall input").prop("checked", pallchkcount === pcheckedcount);
            panel.find(".xcheckall .xcount").html("(" + pcheckedcount + "/" + pallchkcount + ")");
            var texts = pchks.filter(":checked").map(function () {
                return $(this).closest(".xcheckitem").data("text");
            }).get().join();
            if (texts) {
                target.attr("title", texts);
            } else {
                target.removeAttr("title");
            }
            if (pcheckedcount === 0) {
                target.val("请选择" + itemName);
            } else if (pcheckedcount === pallchkcount) {
                target.val("选择了全部" + itemName);
            } else {
                target.val("选择了 " + pcheckedcount + " 项" + itemName);
            }
        }

        panel.click(function (e) { e.stopPropagation(); });
        if (options.multiple) {
            panel.find("input:checkbox").change(function () {
                count($(this).closest(".xmultipanel"), target);
            });

            panel.find(".xcheckall input").click(function () {
                var p = $(this).closest(".xmultipanel");
                var chks = p.find("ul input:checkbox");
                chks.prop("checked", $(this).prop("checked"));
                count(p, target);
            });

            panel.find(".xcheckgroup input").click(function () {
                var chks = $(this).closest("li").find("ul:first input:checkbox");
                chks.prop("checked", $(this).prop("checked"));
                count($(this).closest(".xmultipanel"), target);
            });
        } else {
            panel.find(".xcheckitem").click(function () {
                panel.find(".xselected").removeClass("xselected");
                $(this).addClass("xselected");
                target.attr("title", $(this).data("text"));
                target.val($(this).data("text"));
            });
        }
        $(document).click(function () { close(target, arrow, panel); });

        var value = function (val) {
            if (val === undefined) {
                if (this.options.multiple) {
                    var chks = this.panel.find("li .xcheckitem input:checkbox:checked");
                    if (this.options.groupSelectable) {
                        chks = chks.and(this.panel.find("li .xcheckgroup input:checkbox"));
                    }
                    var vals = chks.map(function () { return $(this).val(); }).get();
                    return vals;
                } else {
                    var slt = this.panel.find("li .xselected");
                    return slt.data("value");
                }
            } else {
                this.panel.find("input:checkbox").prop("checked", false);
                if (this.options.multiple) {
                    var varr = val;
                    if (val && XBox.isString(val)) {
                        varr = val.split(",");
                    }
                    if (XBox.isArray(varr)) {
                        $.each(varr, function (i, v) {
                            var chk = this.panel.find("li .xcheckitem input:checkbox[value=" + v + "]");
                            chk.prop("checked", true);
                        }.bind(this));
                    }
                    count(this.panel, this.target);
                } else {
                    var item = this.panel.find("li .xcheckitem[val=" + val + "]:first");
                    if (item.length) {
                        item.addClass("xselected");
                        var text = item.data("text");
                        target.val(text);
                    }
                }
                return this;
            }
        }

        var control = {
            options: options,
            target: target,
            arrow: arrow,
            panel: panel,
            open: function () { open(target, arrow, panel); },
            close: function () { close(target, arrow, panel); },
            distroy: function () {
                panel.remove();
                arrow.remove();
                target.off("click").removeClass("xmultiselect").removeAttr("readonly");
                target.removeData("xboxui-data");
            }
        }
        control.value = value.bind(control);
        control.value(options.value || null);
        target.data("xboxui-data", control);
        return control;
    };

    return init(options);
}